enum xreg {
    x0=0,
    x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,
    x12,x13,x14,x15,x16,x17,x18,x19,x20,x21,x22,
    x23,x24,x25,x26,x27,x28,x29,x30,x31,
    x_num
};

enum cpu_mode {
    CPU_MODE_U = 0x0,
    CPU_MODE_S = 0x1,
    CPU_MODE_H = 0x2,
    CPU_MODE_M = 0x3
};

struct plock {
    bool flag[2];
    bool victim;
};


struct intrp_desc {
    word source;
    word cause;
};

#define INTR_SRC_SYNC 0
#define INTR_SRC_ASYNC 1

struct rv32cpu {
    magic_t magic;
    word pc;
    enum cpu_mode mode;
    // Q: ring is better?
    struct {
        bool enable; 
        bool hdsig; // handle 信号,至1将在下一个tick立即执行
        bool pending;
        word source;
        word cause;
        struct {
            uint64 head;
            uint64 tail;
            struct intrp_desc data[NR_RING_ITEM];
            struct plock plk;
        } intrp_ring;
    } intrp;
    uint64 mtime; // machine time
    uint64 mtimcmp;
    bool mtie;
    struct {
    bool stopsig;
    bool running;
    //struct plock plk; // 一般情况下只会有CPU线程和另外一个线程同时访问,使用Peterson lock大概率是安全的(已弃用)
    } stat;
    struct environ* env;
    word regs[x_num];
    struct {
    modid_t exhdlr_modid[MAX_MOD_ITEM];
    struct module * exhdlr_base[MAX_MOD_ITEM];
    cpu_exhdlr exhdlr_func[MAX_MOD_ITEM];
    void * exhdlr_ctx[MAX_MOD_ITEM];

    modid_t csrrw_modid[MAX_MOD_ITEM];
    struct module * csrrw_base[MAX_MOD_ITEM];
    cpu_csrrw csrrw_func[MAX_MOD_ITEM];
    void * csrrw_ctx[MAX_MOD_ITEM];

    modid_t decoder_modid[MAX_MOD_ITEM];
    struct module * decoder_base[MAX_MOD_ITEM];
    cpu_decoder decoder_func[MAX_MOD_ITEM];
    void * decoder_ctx[MAX_MOD_ITEM];
    } mods;
    struct {
        pthread_t id;
        pthread_attr_t attr;
        pthread_mutex_t mlk;
    } thread_info;
    pthread_mutex_t ctrl_mlk;
}; // ps: 宏指针名称cpu

// TODO: need input ring
struct devctl {
    magic_t magic;
    struct environ* env;
    struct {
        uint64 head;
        uint64 tail;
        struct dev_csrrw_req data[NR_RING_ITEM];
        struct plock plk;
    } csrrw_ring;
    struct {
        uint64 head;
        uint64 tail;
        struct intrp_desc data[NR_RING_ITEM];
        pthread_mutex_t mlk;
    } intrp_ring;
    struct {
    bool stopsig;
    bool running;
    bool pausesig;
    bool paused;
    pthread_mutex_t blk; // pause用,阻塞线程
    pthread_mutex_t mlk; // 设置sig时用
    } stat;
    struct {
    modid_t csrrw_modid[MAX_MOD_ITEM];
    struct module * csrrw_base[MAX_MOD_ITEM];
    dev_csrrw csrrw_func[MAX_MOD_ITEM];
    void * csrrw_ctx[MAX_MOD_ITEM];
    } mods;
    struct {
        pthread_t id;
        pthread_attr_t attr;
        pthread_mutex_t mlk;
    } thread_info;
    pthread_mutex_t ctrl_mlk;
}; // ps: 宏指针名称dev

struct memory {
    magic_t magic;
    struct environ* env;
    int8 * data;
    memaddr_t size;
    struct {
    modid_t virtrw_modid[MAX_MOD_ITEM];
    struct module * virtrw_base[MAX_MOD_ITEM];
    mem_virtrw virtrw_func[MAX_MOD_ITEM];
    void * virtrw_ctx[MAX_MOD_ITEM];
    
    modid_t phyrw_modid[MAX_MOD_ITEM];
    struct module * phyrw_base[MAX_MOD_ITEM];
    mem_phyrw phyrw_func[MAX_MOD_ITEM];
    void * phyrw_ctx[MAX_MOD_ITEM];
    } mods;
}; // ps: 宏指针名称mem

struct environ {
    uint64 magic;
    enum {
        ENV_STOPPED = 0x0,
        ENV_RUNNING = 0x1,
        ENV_PAUSED = 0x2
    } stat;
    struct rv32cpu cpu;
    struct memory mem;
    struct devctl dctl;
    struct module* mods[MAX_MODS];
    count_t mod_n;
    pthread_mutex_t ctrl_mlk;
    pthread_mutex_t mod_ctrl_mlk;
};

#define ring_full(ring) ((ring.tail+1) % NR_RING_ITEM == ring.head)
#define ring_empty(ring) (ring.tail == ring.head)
// 环状双端队列
// 约定 head==tail为空, tail+1 == head为满
// 操作成功返回1,否则返回0
#define ring_pushhd(ring, item) (ring_full(ring) ? 0 :\
((ring.head?ring.data[--(ring.head)]=item:(ring.data[ring.head=NR_RING_ITEM-1]=item)), 1))

#define ring_pophd(ring, item) (ring_empty(ring) ? 0 :\
(item=ring.data[ring.head], (ring.head==NR_RING_ITEM-1?ring.head=0:ring.head++), 1))

#define ring_pushtl(ring, item) (ring_full(ring) ? 0 :\
(ring.data[ring.tail]=item,ring.tail==NR_RING_ITEM-1?ring.tail=0:ring.tail++, 1))

#define ring_poptl(ring, item) (ring_empty(ring) ? 0 :\
(ring.tail==0?ring.tail=NR_RING_ITEM-1:(ring.tail--, item=ring.data[ring.tail]), 1))


